﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using AppDateService.Contract;
using AppDateService.Contract.Request;
using AppDateService.Model;
using log4net;
using AppDateService.Common;
using AppDateService.Contract.Response;
using System.Drawing;
using System.IO;
using HttpUtils;

namespace AppDateService
{
    // NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "AppDateService" in code, svc and config file together.
    public class AppDateService : IAppDateService
    {
        private static readonly ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
        private AppDateEntities _context = new AppDateEntities();

        #region Master data requests

        public IEnumerable<COccupation> GetOccupations()
        {
            log.Info("Start running service method.");
            var query = from o in _context.Occupations
                        select new COccupation
                        {
                            Code = o.Code,
                            Description = o.Description
                        };

            return query;
        }

        public IEnumerable<CInterest> GetInterests()
        {
            log.Info("Start running service method.");
            var query = from o in _context.Interests
                        select new CInterest
                        {
                            Code = o.Code,
                            Description = o.Description
                        };

            return query;
        }

        public IEnumerable<CLocation> GetLocations()
        {
            log.Info("Start running service method.");
            var query = from o in _context.Locations
                        select new CLocation
                        {
                            Code = o.Code,
                            Description = o.Description
                        };

            return query;
        }

        public ResponseGetFavorites GetFavorites(string token, string nonce, string userId)
        {
            log.Info("Start running service method.");

            ResponseStatus status;
            SessionUtils sessionUtils = new SessionUtils();
            Session session = sessionUtils.CheckSessionTimeout(token, nonce, out status);

            ResponseGetFavorites response = new ResponseGetFavorites();
            LoadSessionInfo(response, session);

            response.Status = status;

            if (status == ResponseStatus.Success)
            {
                try
                {
                    Guid guidUserID = new Guid(userId);

                    response.Favorites = (from uf in _context.UserFavorites
                                          join us in _context.Users
                                          on uf.FavoriteUserID equals us.ID
                                          where uf.UserID == guidUserID
                                          select new CUserFavorite
                                          {
                                              UserID = uf.UserID,
                                              FavoriteUserID = uf.FavoriteUserID,
                                              FavoriteUserName = us.UserName,
                                              AgeFrom = us.AgeFrom,
                                              AgeTo = us.AgeTo,
                                              Location = us.Location,
                                              Timestamp = uf.Timestamp
                                          }).OrderBy(p => p.Timestamp);

                    //response success status                        
                    CreateResponseStatus(response, session, ResponseStatus.Success);
                }
                catch (Exception ex)
                {
                    CreateResponseStatus(response, session, ResponseStatus.Error, ex.Message);
                }
            }
            else
            {
                CreateResponseStatus(response, session, status);
            }

            return response;
        }

        public ResponseSetFavorite SetFavorite(string token, string nonce, string favoriteUserId)
        {
            log.Info("Start running service method.");

            ResponseStatus status;
            SessionUtils sessionUtils = new SessionUtils();
            Session session = sessionUtils.CheckSessionTimeout(token, nonce, out status);

            ResponseSetFavorite response = new ResponseSetFavorite();
            LoadSessionInfo(response, session);

            response.Status = status;
            if (status == ResponseStatus.Success)
            {
                try
                {
                    Guid favoriteUser = new Guid(favoriteUserId);

                    UserFavorite fav = _context.UserFavorites.SingleOrDefault(p => p.UserID == session.UserID && p.FavoriteUserID == favoriteUser);
                    if (fav == null)
                    {
                        fav = _context.UserFavorites.CreateObject();
                        fav.UserID = session.UserID;
                        fav.FavoriteUserID = favoriteUser;
                        fav.Timestamp = DateTime.Now;
                        _context.UserFavorites.AddObject(fav);
                        _context.SaveChanges();
                    }

                    response.Favorites = (from uf in _context.UserFavorites
                                          join us in _context.Users
                                          on uf.FavoriteUserID equals us.ID
                                          where uf.UserID == session.UserID
                                          select new CUserFavorite
                                          {
                                              UserID = uf.UserID,
                                              FavoriteUserID = uf.FavoriteUserID,
                                              FavoriteUserName = us.UserName,
                                              AgeFrom = us.AgeFrom,
                                              AgeTo = us.AgeTo,
                                              Location = us.Location,
                                              Timestamp = uf.Timestamp
                                          }).OrderBy(p => p.Timestamp);

                    //response success status                        
                    CreateResponseStatus(response, session, ResponseStatus.Success);
                }
                catch (Exception ex)
                {
                    CreateResponseStatus(response, session, ResponseStatus.Error, ex.Message);
                }
            }
            else
            {
                CreateResponseStatus(response, session, status);
            }

            return response;
        }
        #endregion

        #region Dating requests

        public ResponseRequestDate RequestDate(string token, string nonce, string userId)
        {
            log.Info("Start running service method.");

            ResponseStatus status;
            SessionUtils sessionUtils = new SessionUtils();
            Session session = sessionUtils.CheckSessionTimeout(token, nonce, out status);

            ResponseRequestDate response = new ResponseRequestDate();
            LoadSessionInfo(response, session);

            response.Status = status;

            if (status == ResponseStatus.Success)
            {
                try
                {
                    Guid guid = Guid.Parse(userId);

                    //Check exist user
                    User user = _context.Users.SingleOrDefault(p => p.ID == guid);
                    if (user == null)
                    {
                        CreateResponseStatus(response, session, ResponseStatus.Error, "User cannot found.");
                        return response;
                    }

                    //Find member in age range criteria
                    int age = (DateTime.Now.Year - user.BirthDate.Year);
                    IEnumerable<DateRequest> requests = _context.DateRequests.Where(p => p.User.AgeFrom <= age && p.User.AgeTo >= age && user.LookingForSex == p.User.Sex);
                    requests = requests.Where(p => user.AgeFrom <= (DateTime.Now.Year - p.User.BirthDate.Year)
                                                && user.AgeTo >= (DateTime.Now.Year - p.User.BirthDate.Year) && user.Sex == p.User.LookingForSex);

                    DateRequest dateRequest = _context.DateRequests.SingleOrDefault(p => p.UserID == guid);

                    if (requests.Count() > 0)
                    {
                        response.RequestDateStatus = "OK";

                        DateRequest person1 = requests.FirstOrDefault();
                        Date date = new Date()
                        {
                            ID = Guid.NewGuid(),
                            UserA = user.ID,
                            UserB = person1.UserID,
                            DatedAt = DateTime.Now,
                            DateStatus = 1
                        };
                        _context.Dates.AddObject(date);
                        _context.SaveChanges();

                        response.NewDate = new CDate
                        {
                            ID = date.ID,
                            UserA = date.UserA,
                            UserB = date.UserB,
                            DatedAt = date.DatedAt,
                            DateStatus = date.DateStatus
                        };

                        _context.DateRequests.DeleteObject(person1);
                        _context.DateRequests.DeleteObject(dateRequest);
                    }
                    else
                    {
                        //Update DateRequest table record
                        if (dateRequest == null)
                        {
                            dateRequest = _context.DateRequests.CreateObject();
                            dateRequest.UserID = guid;
                            dateRequest.Timestamp = DateTime.Now;

                            _context.DateRequests.AddObject(dateRequest);
                        }
                        else
                        {
                            dateRequest.Timestamp = DateTime.Now;
                        }
                        _context.SaveChanges();
                        response.RequestDateStatus = "Pending";
                    }

                    //response success status                        
                    CreateResponseStatus(response, session, ResponseStatus.Success);
                }
                catch (Exception ex)
                {
                    CreateResponseStatus(response, session, ResponseStatus.Error, ex.Message);
                }
            }
            else
            {
                CreateResponseStatus(response, session, status);
            }

            return response;
        }

        public ResponseCancelDate CancelDate(string token, string nonce, string dateId)
        {
            log.Info("Start running service method.");

            ResponseStatus status;
            SessionUtils sessionUtils = new SessionUtils();
            Session session = sessionUtils.CheckSessionTimeout(token, nonce, out status);

            ResponseCancelDate response = new ResponseCancelDate();
            LoadSessionInfo(response, session);

            response.Status = status;
            if (status == ResponseStatus.Success)
            {
                try
                {
                    Guid guid = Guid.Parse(dateId);
                    Date date = _context.Dates.SingleOrDefault(p => p.ID == guid);
                    if (date != null)
                    {
                        date.DateStatus = 2;
                        _context.SaveChanges();
                        CreateResponseStatus(response, session, ResponseStatus.Success);
                    }
                    else
                    {
                        CreateResponseStatus(response, session, ResponseStatus.Error, "Date cannot found.");
                    }
                }
                catch (Exception ex)
                {
                    CreateResponseStatus(response, session, ResponseStatus.Error, ex.Message);
                }
            }
            else
            {
                CreateResponseStatus(response, session, status);
            }

            return response;
        }

        public ResponseRequestDate StatusPendingDate(string token, string nonce, string userId)
        {
            log.Info("Start running service method.");

            ResponseStatus status;
            SessionUtils sessionUtils = new SessionUtils();
            Session session = sessionUtils.CheckSessionTimeout(token, nonce, out status);

            ResponseRequestDate response = new ResponseRequestDate();
            LoadSessionInfo(response, session);

            response.Status = status;

            if (status == ResponseStatus.Success)
            {
                try
                {
                    Guid guid = Guid.Parse(userId);

                    //Check exist user
                    User user = _context.Users.SingleOrDefault(p => p.ID == guid);
                    if (user == null)
                    {
                        CreateResponseStatus(response, session, ResponseStatus.Error, "User cannot found.");
                        return response;
                    }

                    //Find member in age range criteria
                    int age = (DateTime.Now.Year - user.BirthDate.Year);
                    IEnumerable<DateRequest> requests = _context.DateRequests.Where(p => p.User.AgeFrom <= age && p.User.AgeTo >= age && user.LookingForSex == p.User.Sex);
                    requests = requests.Where(p => user.AgeFrom <= (DateTime.Now.Year - p.User.BirthDate.Year)
                                                && user.AgeTo >= (DateTime.Now.Year - p.User.BirthDate.Year) && user.Sex == p.User.LookingForSex);

                    DateRequest dateRequest = _context.DateRequests.SingleOrDefault(p => p.UserID == guid);
                    if (requests.Count() > 0)
                    {
                        response.RequestDateStatus = "OK";

                        DateRequest person1 = requests.FirstOrDefault();
                        Date date = new Date()
                        {
                            ID = Guid.NewGuid(),
                            UserA = user.ID,
                            UserB = person1.UserID,
                            DatedAt = DateTime.Now,
                            DateStatus = 1
                        };
                        _context.Dates.AddObject(date);
                        _context.SaveChanges();

                        response.NewDate = new CDate
                        {
                            ID = date.ID,
                            UserA = date.UserA,
                            UserB = date.UserB,
                            DatedAt = date.DatedAt,
                            DateStatus = date.DateStatus
                        };

                        _context.DateRequests.DeleteObject(person1);
                        _context.DateRequests.DeleteObject(dateRequest);
                    }
                    else
                    {
                        //Update DateRequest table record
                        if (dateRequest == null)
                        {
                            dateRequest = _context.DateRequests.CreateObject();
                            dateRequest.UserID = guid;
                            dateRequest.Timestamp = DateTime.Now;

                            _context.DateRequests.AddObject(dateRequest);
                        }
                        else
                        {
                            dateRequest.Timestamp = DateTime.Now;
                        }
                        _context.SaveChanges();
                        response.RequestDateStatus = "Pending";
                    }

                    //response success status                        
                    CreateResponseStatus(response, session, ResponseStatus.Success);
                }
                catch (Exception ex)
                {
                    CreateResponseStatus(response, session, ResponseStatus.Error, ex.Message);
                }
            }

            return response;
        }

        #endregion

        #region User account manipulation requests

        public ResponseLoginAccount LoginAccount(RequestLoginAccount loginInfo)
        {
            log.Info("Start running service method.");

            ResponseLoginAccount response = new ResponseLoginAccount();
            CUser userDB = (from c in _context.Users.Include("Occupation1").Where(p => p.UserName == loginInfo.UserName && p.Password == loginInfo.Password)
                            select new CUser
                            {
                                ID = c.ID,
                                UserName = c.UserName,
                                Password = c.Password,
                                Sex = c.Sex,
                                LookingForSex = c.LookingForSex,
                                BirthDate = c.BirthDate,
                                AgeFrom = c.AgeFrom,
                                AgeTo = c.AgeTo,
                                AcceptOnlyMatchingAges = c.AcceptOnlyMatchingAges,
                                Location = c.Location,
                                HasPremium = c.HasPremium,
                                Active = c.Active,
                                //Image = c.Image,
                                Description = c.Description,
                                OccupationCode = c.Occupation1 != null ? c.Occupation1.Code : "",
                                OccupationDescription = c.Occupation1 != null ? c.Occupation1.Description : ""
                            }).FirstOrDefault();

            if (userDB != null)
            {
                //Authenticated
                Session session = (new SessionUtils()).CreateSession(userDB);
                LoadSessionInfo(response, session);

                //set user infor to return
                response.User = userDB;
            }
            else
            {
                response.Status = ResponseStatus.Unanthenticated;
                response.ErrorMessage = "Login failed.";
            }

            return response;
        }

        public ResponseLoginAccount CheckLoginAccount(string username, string password)
        {
            log.Info("Start running service method.");

            ResponseLoginAccount response = new ResponseLoginAccount();
            CUser userDB = (from c in _context.Users.Include("Occupation1").Where(p => p.UserName == username && p.Password == password)
                            select new CUser
                            {
                                ID = c.ID,
                                UserName = c.UserName,
                                Password = c.Password,
                                Sex = c.Sex,
                                LookingForSex = c.LookingForSex,
                                BirthDate = c.BirthDate,
                                AgeFrom = c.AgeFrom,
                                AgeTo = c.AgeTo,
                                AcceptOnlyMatchingAges = c.AcceptOnlyMatchingAges,
                                Location = c.Location,
                                HasPremium = c.HasPremium,
                                Active = c.Active,
                                //Image = c.Image,
                                Description = c.Description,
                                OccupationCode = c.Occupation1 != null ? c.Occupation1.Code : "",
                                OccupationDescription = c.Occupation1 != null ? c.Occupation1.Description : ""
                            }).FirstOrDefault();

            if (userDB != null)
            {
                //Authenticated
                Session session = (new SessionUtils()).CreateSession(userDB);
                LoadSessionInfo(response, session);

                //set user infor to return
                response.User = userDB;
            }
            else
            {
                response.Status = ResponseStatus.Unanthenticated;
                response.ErrorMessage = "Login failed.";
            }

            return response;
        }

        public string RegisterAccount(RequestRegisterAccount account)
        {
            log.Info("Start running service method.");
            if (!string.IsNullOrEmpty(account.UserName) && _context.Users.SingleOrDefault(p => p.UserName == account.UserName) == null)
            {
                User newUser = new User
                {
                    ID = Guid.NewGuid(),
                    UserName = account.UserName,
                    Password = account.Password,
                    Sex = account.Sex,
                    LookingForSex = account.LookingForSex,
                    BirthDate = account.BirthDate,
                    AgeFrom = account.AgeFrom,
                    AgeTo = account.AgeTo,
                    AcceptOnlyMatchingAges = account.AcceptOnlyMatchingAges,
                    Location = account.Location,
                    HasPremium = account.HasPremium,
                    Active = account.Active,
                    //Image = account.Image,
                    Description = account.Description,
                    Occupation = account.OccupationCode
                };

                //add new Locations
                foreach (string location in account.Locations)
                {
                    Location loc = _context.Locations.SingleOrDefault(p => p.Code == location);
                    newUser.Locations.Add(loc);
                }
                //add new Interests
                foreach (string interest in account.Interests)
                {
                    Interest inter = _context.Interests.SingleOrDefault(p => p.Code == interest);
                    newUser.Interests.Add(inter);
                }
                _context.Users.AddObject(newUser);

                if (_context.SaveChanges() > 0)
                {
                    return newUser.ID.ToString();
                }
            }

            return "";
        }

        public ResponseEditAccount EditAccount(RequestEditAccount message)
        {
            log.Info("Start running service method.");

            ResponseEditAccount response = new ResponseEditAccount();
            ResponseStatus status;
            SessionUtils sessionUtils = new SessionUtils();
            Session session = sessionUtils.CheckSessionTimeout(message.Token, message.Nonce, out status);
            if (status == ResponseStatus.Success)
            {
                try
                {
                    User user = _context.Users.SingleOrDefault(p => p.UserName == message.User.UserName);
                    if (user != null)
                    {
                        {
                            user.Sex = message.User.Sex;
                            user.LookingForSex = message.User.LookingForSex;
                            user.BirthDate = message.User.BirthDate;
                            user.AgeFrom = message.User.AgeFrom;
                            user.AgeTo = message.User.AgeTo;
                            user.AcceptOnlyMatchingAges = message.User.AcceptOnlyMatchingAges;
                            user.Location = message.User.Location;
                            user.HasPremium = message.User.HasPremium;
                            user.Active = message.User.Active;
                            //user.Image = message.User.Image;
                            user.Description = message.User.Description;
                            user.Occupation = message.User.OccupationCode;
                        }

                        // remove location
                        foreach (Location location in user.Locations.Where(p => !message.Locations.Contains(p.Code)))
                        {
                            user.Locations.Remove(location);
                        }
                        //add new location
                        foreach (string location in message.Locations.Where(p => !(from lo in user.Locations select lo.Code).Contains(p)))
                        {
                            Location loc = _context.Locations.SingleOrDefault(p => p.Code == location);
                            user.Locations.Add(loc);
                        }

                        // remove interest
                        foreach (Interest interest in user.Interests.Where(p => !message.Interests.Contains(p.Code)))
                        {
                            user.Interests.Remove(interest);
                        }

                        //add new interest
                        foreach (string interest in message.Interests.Where(p => !(from lo in user.Interests select lo.Code).Contains(p)))
                        {
                            Interest inter = _context.Interests.SingleOrDefault(p => p.Code == interest);
                            user.Interests.Add(inter);
                        }

                        _context.SaveChanges();

                        //response success status                        
                        CreateResponseStatus(response, session, ResponseStatus.Success);
                    }
                    else
                    {
                        string errorMsg = string.Format("User [{0}] cannot be found.", message.User.UserName);
                        CreateResponseStatus(response, session, ResponseStatus.Error, errorMsg);
                    }
                }
                catch (Exception ex)
                {
                    CreateResponseStatus(response, session, ResponseStatus.Error, ex.Message);
                }
            }
            else
            {
                CreateResponseStatus(response, session, status);
            }

            return response;
        }

        public ResponseExtendedUserInfo RequestExtendedUserInfo(string token, string nonce, string dateId)
        {
            log.Info("Start running service method.");

            ResponseStatus status;
            SessionUtils sessionUtils = new SessionUtils();
            Session session = sessionUtils.CheckSessionTimeout(token, nonce, out status);

            ResponseExtendedUserInfo response = new ResponseExtendedUserInfo();
            LoadSessionInfo(response, session);

            response.Status = status;
            if (status == ResponseStatus.Success)
            {
                try
                {
                    User loggedUser = _context.Users.SingleOrDefault(p => p.ID == session.UserID);
                    if (!loggedUser.HasPremium)
                    {
                        status = ResponseStatus.RestrictedAccess;
                    }
                    Guid guid = Guid.Parse(dateId);
                    Date date = _context.Dates.Include("User").Include("User1").SingleOrDefault(p => p.ID == guid);
                    if (date != null)
                    {
                        response.UserA = ConvertTo(date.User);
                        response.UserB = ConvertTo(date.User1);
                        response.DateStatus = date.DateStatus;
                    }

                    //response success status                        
                    CreateResponseStatus(response, session, ResponseStatus.Success);
                }
                catch (Exception ex)
                {
                    CreateResponseStatus(response, session, ResponseStatus.Error, ex.Message);
                }
            }
            else
            {
                CreateResponseStatus(response, session, status);
            }

            return response;
        }
        
        public bool ExistsUsername(string username)
        {
            return _context.Users.Where(p => p.UserName == username).Count() > 0;
        }
        #endregion

        #region Message handle requests

        public ResponseNewMessages GetNewMessages(string token, string nonce, string dateId, string lastMessageId)
        {
            log.Info("Start running service method.");

            ResponseNewMessages response = new ResponseNewMessages();
            ResponseStatus status;
            SessionUtils sessionUtils = new SessionUtils();
            Session session = sessionUtils.CheckSessionTimeout(token, nonce, out status);
            if (status == ResponseStatus.Success)
            {
                try
                {
                    Guid id = new Guid(dateId);

                    int msgID = int.Parse(lastMessageId);

                    DateMessage lastMessage = _context.DateMessages.SingleOrDefault(p => p.DateID == id && p.MessageID == msgID && (p.Date.UserA == session.UserID || p.Date.UserB == session.UserID));

                    response.NewMessages = from d in _context.DateMessages.Include("User").Where(p => p.DateID == id && p.Timestamp > lastMessage.Timestamp)
                                           select new CDateMessage()
                                           {
                                               DateID = d.DateID,
                                               FromUser = new CUser()
                                               {
                                                   ID = d.User.ID,
                                                   UserName = d.User.UserName,
                                                   Sex = d.User.Sex,
                                                   BirthDate = d.User.BirthDate,
                                                   Location = d.User.Location,
                                                   HasPremium = d.User.HasPremium,
                                                   Active = d.User.Active,
                                                   Description = d.User.Description,
                                                   OccupationDescription = d.User.Occupation1 != null ? d.User.Occupation1.Description : ""
                                               },
                                               MessageID = d.MessageID,
                                               MessageText = d.MessageText,
                                               Image = d.Image,
                                               Timestamp = d.Timestamp
                                           };
                    CreateResponseStatus(response, session, ResponseStatus.Success);
                }
                catch (Exception ex)
                {
                    CreateResponseStatus(response, session, ResponseStatus.Error, ex.Message);
                }
            }
            else
            {
                CreateResponseStatus(response, session, status);
            }

            return response;
        }

        public ResponseSendMessage SendMessage(RequestSendMessage message)
        {
            log.Info("Start running service method.");

            ResponseSendMessage response = new ResponseSendMessage();
            ResponseStatus status;
            SessionUtils sessionUtils = new SessionUtils();
            Session session = sessionUtils.CheckSessionTimeout(message.Token, message.Nonce, out status);
            if (status == ResponseStatus.Success)
            {
                try
                {
                    //Get new messageID
                    int newMessageID = (_context.DateMessages.Where(p => p.DateID == message.DateID).Max(p => (int?)p.MessageID) ?? 0) + 1;

                    DateMessage newDate = new DateMessage()
                    {
                        DateID = message.DateID,
                        FromUser = message.FromUser,
                        MessageID = newMessageID,
                        MessageText = message.MessageText,
                        Timestamp = DateTime.Now
                    };

                    _context.DateMessages.AddObject(newDate);
                    _context.SaveChanges();

                    response.MessageID = newMessageID;
                    //response success status                        
                    CreateResponseStatus(response, session, ResponseStatus.Success);
                }
                catch (Exception ex)
                {
                    CreateResponseStatus(response, session, ResponseStatus.Error, ex.Message);
                }
            }
            else
            {
                CreateResponseStatus(response, session, status);
            }

            return response;
        }

        #endregion

        #region Image requests
        public Stream GetUserImage(string token, string nonce, string userId)
        {
            log.Info("Start running service method.");

            ResponseStatus status;
            SessionUtils sessionUtils = new SessionUtils();
            Session session = sessionUtils.CheckSessionTimeout(token, nonce, out status, true);

            ResponseUserImage response = new ResponseUserImage();
            LoadSessionInfo(response, session);

            response.Status = status;
            if (status == ResponseStatus.Success)
            {
                try
                {
                    User loggedUser = _context.Users.SingleOrDefault(p => p.ID == session.UserID);
                    if (!loggedUser.HasPremium)
                    {
                        status = ResponseStatus.RestrictedAccess;
                    }
                    Guid id = new Guid(userId);
                    User user = _context.Users.SingleOrDefault(p => p.ID == id);
                    if (user != null)
                    {
                        MemoryStream ms = new MemoryStream(user.Image);
                        return ms;
                    }
                    else
                    {
                        string errorMsg = string.Format("User [{0}] cannot be found.", id);
                        CreateResponseStatus(response, session, ResponseStatus.Error, errorMsg);
                    }
                }
                catch (Exception ex)
                {
                    CreateResponseStatus(response, session, ResponseStatus.Error, ex.Message);
                }
            }
            else
            {
                CreateResponseStatus(response, session, status);
            }

            return null;
        }

        public Stream GetMessageImage(string token, string nonce, string dateId, string messageId)
        {
            log.Info("Start running service method.");

            ResponseStatus status;
            SessionUtils sessionUtils = new SessionUtils();
            Session session = sessionUtils.CheckSessionTimeout(token, nonce, out status, true);

            ResponseUserImage response = new ResponseUserImage();
            LoadSessionInfo(response, session);

            response.Status = status;
            if (status == ResponseStatus.Success)
            {
                try
                {
                    Guid guidDateId = Guid.Parse(dateId);
                    int iMsgID = int.Parse(messageId);
                    DateMessage dateMsg = _context.DateMessages.SingleOrDefault(p => p.DateID == guidDateId && p.MessageID == iMsgID);

                    if (dateMsg != null)
                    {
                        MemoryStream ms = new MemoryStream(dateMsg.Image);
                        return ms;
                    }
                    else
                    {
                        string errorMsg = "Date message cannot be found.";
                        CreateResponseStatus(response, session, ResponseStatus.Error, errorMsg);
                    }
                }
                catch (Exception ex)
                {
                    CreateResponseStatus(response, session, ResponseStatus.Error, ex.Message);
                }
            }
            else
            {
                CreateResponseStatus(response, session, status);
            }

            return null;
        }

        public ResponseUploadUserImage UploadUserImage(Stream uploadFile)
        {
            log.Info("Start running service method.");

            HttpMultipartParser parser = new HttpMultipartParser(uploadFile, "uploadfile");
            string userId = parser.Parameters["userid"];
            string token = parser.Parameters["token"];
            string nonce = parser.Parameters["nonce"];

            ResponseUploadUserImage response = new ResponseUploadUserImage();
            ResponseStatus status;
            SessionUtils sessionUtils = new SessionUtils();
            Session session = sessionUtils.CheckSessionTimeout(token, nonce, out status, true);
            if (status == ResponseStatus.Success)
            {
                try
                {
                    Guid guidUserID = Guid.Parse(userId);
                    User user = _context.Users.SingleOrDefault(p => p.ID == guidUserID);
                    if (user != null)
                    {
                        //Get all byte from uploadStream
                        user.Image = parser.FileContents;

                        //Then save into DB
                        _context.SaveChanges();

                        //response success status                        
                        CreateResponseStatus(response, session, ResponseStatus.Success);
                    }
                    else
                    {
                        string errorMsg = string.Format("User [{0}] cannot be found.", userId);
                        CreateResponseStatus(response, session, ResponseStatus.Error, errorMsg);
                    }
                }
                catch (Exception ex)
                {
                    CreateResponseStatus(response, session, ResponseStatus.Error, ex.Message);
                }
            }
            else
            {
                CreateResponseStatus(response, session, status);
            }

            return response;
        }

        public ResponseUploadMessageImage UploadMessageImage(Stream uploadFile)
        {
            log.Info("Start running service method.");

            HttpMultipartParser parser = new HttpMultipartParser(uploadFile, "uploadfile");
            Guid dateID = Guid.Parse(parser.Parameters["dateid"]);
            int messageID = int.Parse(parser.Parameters["messageid"]);
            string token = parser.Parameters["token"];
            string nonce = parser.Parameters["nonce"];

            ResponseUploadMessageImage response = new ResponseUploadMessageImage();
            ResponseStatus status;
            SessionUtils sessionUtils = new SessionUtils();
            Session session = sessionUtils.CheckSessionTimeout(token, nonce, out status, true);
            if (status == ResponseStatus.Success)
            {
                try
                {
                    DateMessage dMsg = _context.DateMessages.SingleOrDefault(p => p.DateID == dateID
                                                                               && p.MessageID == messageID);
                    if (dMsg != null)
                    {
                        //Get all byte from uploadStream
                        dMsg.Image = parser.FileContents;

                        //Then save into DB
                        _context.SaveChanges();

                        //response success status                        
                        CreateResponseStatus(response, session, ResponseStatus.Success);
                    }
                    else
                    {
                        string errorMsg = "DateMessage cannot be found.";
                        CreateResponseStatus(response, session, ResponseStatus.Error, errorMsg);
                    }
                }
                catch (Exception ex)
                {
                    CreateResponseStatus(response, session, ResponseStatus.Error, ex.Message);
                }
            }
            else
            {
                CreateResponseStatus(response, session, status);
            }

            return response;
        }
        #endregion

        #region Helpers

        private CUser ConvertTo(User user)
        {
            return new CUser
            {
                ID = user.ID,
                UserName = user.UserName,
                Password = user.Password,
                Sex = user.Sex,
                LookingForSex = user.LookingForSex,
                BirthDate = user.BirthDate,
                AgeFrom = user.AgeFrom,
                AgeTo = user.AgeTo,
                AcceptOnlyMatchingAges = user.AcceptOnlyMatchingAges,
                Location = user.Location,
                HasPremium = user.HasPremium,
                Active = user.Active,
                Description = user.Description,
                OccupationCode = user.Occupation1 != null ? user.Occupation1.Code : "",
                OccupationDescription = user.Occupation1 != null ? user.Occupation1.Description : ""
            };
        }
        private static void LoadSessionInfo(AuthResponseBase response, Session session)
        {
            response.Nonce = session.Nonce;
            response.Token = session.Token;            
            //response.Timestamp = DateTime.Now.ToString("yyyyMMddHHmmssffff");
        }

        private static void CreateResponseStatus(AuthResponseBase response, Session session, ResponseStatus status, string errorMsg = "")
        {
            response.Status = status;
            response.Token = session.Token;
            response.Nonce = session.Nonce;
            //response.Timestamp = DateTime.Now.ToString("yyyyMMddHHmmssffff");

            if (status == ResponseStatus.Success)
            {
                log.Info("Running service method success.");
            }
            else if (status == ResponseStatus.Error)
            {
                log.Error(errorMsg);
            }
            else
            {
                log.Info(errorMsg);
            }
        }
        #endregion
    }
}
